package com.crb.crm.manage.service.biz.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.crb.crm.manage.enums.ExcelType;
import com.crb.crm.manage.enums.OssType;
import com.crb.crm.manage.dao.biz.UploadRecordInfoMapper;
import com.crb.crm.manage.dao.biz.UploadRecordMapper;
import com.crb.crm.manage.entity.biz.UploadRecordDTO;
import com.crb.crm.manage.entity.biz.UploadRecordSearchDTO;
import com.crb.crm.manage.excel.ExcelTemplate;
import com.crb.crm.manage.excel.listener.BaseExcelListener;
import com.crb.crm.manage.excel.listener.ExcelListenerCtx;
import com.crb.crm.manage.oos.OSSUtilCtx;
import com.crb.crm.manage.pojo.User;
import com.crb.crm.manage.pojo.biz.UploadRecord;
import com.crb.crm.manage.service.biz.UploadRecordService;
import com.crb.crm.manage.utils.DateUtil;
import com.crb.crm.manage.utils.PageDataResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.*;

/**
 * @author huangjian
 */
@Service
public class UploadRecordServiceImpl implements UploadRecordService {
	private static final Logger logger = LoggerFactory.getLogger(UploadRecordServiceImpl.class);

	@Autowired
	private ExcelListenerCtx excelListenerCtx;
	@Autowired
	private OSSUtilCtx ossUtilCtx;
	@Autowired
	private UploadRecordInfoMapper infoMapper;
	@Resource
	private UploadRecordMapper mapper;
	@Override
	public PageDataResult getUploadRecords(UploadRecordSearchDTO search, Integer page, Integer limit) {
		// 时间处理
		if (null != search) {
			if (StringUtils.isNotEmpty(search.getQinsertTimeStart())
					&& StringUtils.isEmpty(search.getQinsertTimeEnd())) {
				search.setQinsertTimeEnd(DateUtil.format(new Date()));
			} else if (StringUtils.isEmpty(search.getQinsertTimeStart())
					&& StringUtils.isNotEmpty(search.getQinsertTimeEnd())) {
				search.setQinsertTimeStart(DateUtil.format(new Date()));
			}
			if (StringUtils.isNotEmpty(search.getQinsertTimeStart())
					&& StringUtils.isNotEmpty(search.getQinsertTimeEnd())) {
				if (search.getQinsertTimeEnd().compareTo(search.getQinsertTimeStart()) < 0) {
					String temp = search.getQinsertTimeStart();
					search.setQinsertTimeStart(search.getQinsertTimeEnd());
					search.setQinsertTimeEnd(temp);
				}
			}
		}
		PageDataResult pdr = new PageDataResult();
		PageHelper.startPage(page, limit);
		List<UploadRecordDTO> urList = infoMapper.getUploadRecords(search);
		// 获取分页查询后的数据
		PageInfo<UploadRecordDTO> pageInfo = new PageInfo<>(urList);
		// 设置获取到的总记录数total：
		pdr.setTotals(Long.valueOf(pageInfo.getTotal()).intValue());
		pdr.setList(urList);
		return pdr;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Map<String, Object> upload(MultipartFile file, String templateCode, User existUser) {
		ExcelTemplate byTemplateCode = ExcelTemplate.findByTemplateCode(templateCode);
		Map<String, Object> map = new HashMap<>();
		map.put("close", "0");
		try {
			String batchNo=String.valueOf(System.currentTimeMillis());
			BaseExcelListener baseExcelListener = excelListenerCtx.chooseOne(byTemplateCode);
			EasyExcel.read(file.getInputStream(),baseExcelListener.rowModelClass(), baseExcelListener).sheet().doRead();
			List errorList = baseExcelListener.getErrorList();
			String outFileName=null;
			OssType ossType = ossUtilCtx.getOssType();
			if(!CollectionUtils.isEmpty(errorList)){
				outFileName= batchNo+ ".xlsx";
				InputStream inputStream = writeExcel(baseExcelListener.rowModelClass(), errorList);
				String destination = ExcelType.ERROR.getFoder() +"/"+outFileName;
				if(ossType==OssType.OSS_QINIU){
					destination=outFileName;
				}
				boolean upload = ossUtilCtx.upload(inputStream, destination);
				if(!upload){
					map.put("msg", "操作失败，上传文件失败");
				}else{
					map.put("msg", "上传数据有【"+errorList.size()+"】条是失败的..");
				}
			}else{
				map.put("msg", "ok");
			}
			String srcFileName = byTemplateCode.getDesc().concat("源文件").concat("-").concat(batchNo).concat(".xlsx");
			String destination = ExcelType.ORIGINAL.getFoder() +"/"+srcFileName;
			if(ossType==OssType.OSS_QINIU){
				destination=srcFileName;
			}
			boolean upload = ossUtilCtx.upload(file.getInputStream(), destination);
			if(!upload){
				map.put("msg", "操作失败，上传文件失败");
			}else{
				UploadRecord record = new UploadRecord();
				record.setErrFileId(outFileName);
				record.setInsertTime(new Date());
				record.setBatchNo(batchNo);
				record.setIsDel(false);
				record.setTotal(baseExcelListener.getTotalCount());
				record.setSuccess(baseExcelListener.getTotalCount()-errorList.size());
				record.setFailed(errorList.size());
				record.setSrcFileId(srcFileName);
				record.setOperator(existUser.getUsername());
				record.setModel(byTemplateCode.getDesc());
				record.setOssType(ossType.name());
				mapper.insertSelective(record);
				logger.debug("批量上传完成！map=" + map);
				map.put("close", "1");
			}
			return map;
		} catch (Exception e) {
			e.printStackTrace();
			if(e instanceof ExcelAnalysisException){
				map.put("msg", e.getCause().getMessage());
				logger.error("上传异常", e);
				return map;
			}
			map.put("msg", "批量上传错误，请您稍后再试");
			logger.error("批量上传异常！", e);
			return map;
		}
	}


	/**
	 *
	 * @param clazz Excel实体映射类
	 * @param dataList 导出数据
	 * @return
	 */
	private InputStream writeExcel(Class<? extends BaseRowModel> clazz,
								   List<? extends BaseRowModel> dataList){
		try {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
			// 设置SHEET
			Sheet sheet = new Sheet(1, 0);
			sheet.setSheetName("错误文件");
			// 设置标题
			Table table = new Table(1);
			table.setClazz(clazz);
			writer.write0(dataList, sheet, table);
			writer.finish();
			return new ByteArrayInputStream(out.toByteArray());
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}
